﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Thrift.Protocol;
using Thrift.Transport;
using System.Threading;

using HelloThriftspace;
using InputOutputSpace;
using FileTransportSpace;
using System.IO;
using Thrift.IL;
using System.Management;
using RemoteCommandSpace;
using Project.InterceptionBehaviors;

namespace Thrift.Client
{
    class Program
    {
        private static object objLock = new object();
        /// <summary>
        /// 从一个文件写到另一个文件
        /// 1 1.zip是已存在的文件，以FileMode.Open的方式将数据读取到byte[]数组中；
        /// 2 while循环中，每次最多读取1024 * 1024 * 4 字节，这我称作是缓冲区大小；
        /// 3 当读到最后一次的时候，byte[]数组可能不满，这时，readBytes将是byte[]实际的容量
        /// 4 while循环读取的时候，流中的seek或者是position会自动偏移处理，所以这并需要我们维护读取开始的位置
        /// </summary>
        static void BeforeReadThenWirte()
        {

            using (FileStream fs = new FileStream("D:\\照片\\psu2.jpg", FileMode.Open, FileAccess.Read))//读出,读多少就写多少
            {
                //缓冲区太小的话，速度慢而且伤硬盘
                //声明一个4兆字节缓冲区大小，比如迅雷也有一个缓冲区，如果没有缓冲区的话，
                //每下载一个字节都要往磁盘进行写，非常伤磁盘，所以，先往内存的缓冲区写字节，当
                //写够了一定容量之后，再往磁盘进行写操作，减低了磁盘操作。
                byte[] buffer = new byte[1024 * 1024 * 4];//开避4M的缓冲区,也可以设为0x1000为4K
                int readBytes;
                //第二个参数Offset表示当前位置的偏移量，一般都传0
                while ((readBytes = fs.Read(buffer, 0, buffer.Length)) > 0) //读取的位置自动往后挪动。
                {
                    using (FileStream stream = new FileStream("d:\\upload\\test.jpg", FileMode.Append, FileAccess.Write))
                    {
                        //readBytes为实际读到的byte数，因为最后一次可能不会读满。
                        stream.Write(buffer, 0, readBytes);
                    }
                }
            }

            Console.ReadKey();
        }

        static void BeforeWirteThenRead()
        {
            using (FileStream stream = new FileStream("d:\\upload\\test.jpg", FileMode.Append, FileAccess.Write))
            {

                byte[] buffer = new byte[1024 * 1024 * 4];
                int readBytes;
                using (FileStream fs = new FileStream("D:\\照片\\psu2.jpg", FileMode.Open, FileAccess.Read))
                {
                    while ((readBytes = fs.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        stream.Write(buffer, 0, readBytes);
                    }
                }

            }

            Console.ReadKey();
        }

        static void Main(string[] args)
        {
            try
            {

                Project.IoC.ServiceLocator.Instance
                                          .GetService<IHandle>()
                                          .Handle();

                string server = "192.168.2.71";

                TTransport transport0 = new TSocket(server, 9800);
                TProtocol protocol0 = new TBinaryProtocol(transport0);
                RemoteCommand.Client client0 = new RemoteCommand.Client(new TMultiplexedProtocol(protocol0, "RemoteCommandHandler"));
                transport0.Open();
                Console.WriteLine("远程命令调用");
                client0.Send(new RemoteCommandData { Data = "notepad" });
                transport0.Close();


                TTransport transport = new TSocket(server, 9090);
                TProtocol protocol = new TBinaryProtocol(transport);


                TMultiplexedProtocol mp1 = new TMultiplexedProtocol(protocol, "HelloThriftHandler");
                HelloThrift.Client client = new HelloThrift.Client(mp1);

                InputOutput.Client clientInputOutput = new InputOutput.Client(new TMultiplexedProtocol(protocol, "InputOutputHandler"));

                transport.Open();

                client.HelloWorld();
                Console.WriteLine(clientInputOutput.inputStr("占占"));
                transport.Close();



                #region 文件上传下载
                var transport3 = new TSocket(server, 9900);
                var fileTransport = new FileTransport.Client(new TMultiplexedProtocol(new TBinaryProtocol(transport3), "FileTransportHandler"));
                transport3.Open();
                string fromPath = "f:\\[电影天堂www.dy2018.net]纵贯线2010台北演唱会：出发.1024x576.国语中字.mkv";
                string toPath = "d:\\path\\";
                string downPath = "d:\\downloads\\";
                //FileTransportService.UploadTaskTest(transport3, fileTransport, fromPath, toPath);
                FileTransportService.DownLoadTest(transport3, fileTransport, fromPath, downPath);
                // transport3.Close(); //不能在这里关闭链接，因为线程不会阻塞主线程的执行
                #endregion

                Console.ReadKey();
            }
            catch (Exception ex)
            {
                throw;
            }

        }

        /// <summary>
        /// 分块上传
        /// </summary>
        /// <param name="fileTransport"></param>
        /// <param name="fromPath"></param>
        /// <param name="toPath"></param>
        static void UploadTest(FileTransport.Client fileTransport, string fromPath, string toPath)
        {
            var sync = fileTransport.IsSync(toPath + Path.GetFileName(fromPath), ClientKey);
            if (sync.IsSync)//是否要进行继传
            {
                #region 上传
                //客户端发请求
                using (FileStream fs = new FileStream(fromPath, FileMode.Open, FileAccess.Read))
                {
                    byte[] buffer = new byte[1024 * 1024 * 4];//开避4M的缓冲区0x1000为4K
                    int readBytes;

                    fs.Position = sync.CurrentSeek;//默认值，如果是断点续传，需要存储当前position的位置
                    while ((readBytes = fs.Read(buffer, 0, buffer.Length)) > 0) //读取的位置自动往后挪动。
                    {
                        fileTransport.Upload(new DataSegment
                        {
                            CurrentBytes = readBytes,
                            CurrentSeek = fs.Position,
                            Data = buffer,
                            Filename = toPath + Path.GetFileName(fromPath),
                            FileSize = fs.Length
                        });
                        Console.WriteLine("已经上传了{0},共{1}", buffer.Length, fs.Length);

                    }

                    fileTransport.UpdateDataSync(new DataSync
                    {
                        FilePath = toPath + Path.GetFileName(fromPath),
                        IsSync = false,
                        CurrentSeek = 0,
                        ClientKey = ClientKey,
                    });
                    Console.WriteLine("文件上传成功！");


                }
                #endregion
            }
            else
            {
                Console.WriteLine("文件已经上传！");
            }
        }

        static void UploadThreadTest(FileTransport.Client fileTransport, string fromPath, string toPath)
        {
            int block = 1024 * 1024 * 4;
            byte[] buffer = new byte[block];
            long filesize = new FileInfo(fromPath).Length;
            int readBytes = 0;
            int count = 0;


            for (long i = 0; i <= filesize; i += block)
            {
                Thread t1 = new Thread(() =>
                {
                    using (FileStream fs = new FileStream(fromPath, FileMode.Open, FileAccess.Read))
                    {
                        count++;
                        fs.Position = i;
                        readBytes = fs.Read(buffer, 0, buffer.Length);
                        bool res = fileTransport.Upload(new DataSegment
                        {
                            CurrentBytes = readBytes,
                            CurrentSeek = fs.Position,
                            Data = buffer,
                            Filename = toPath + Path.GetFileName(fromPath),
                            FileSize = filesize,
                            OrderNumber = count,
                        });
                        Console.Write("当前发送了请求:{0}个,", count);

                        if (res)
                            Console.WriteLine("已经上传了{0},共{1}", buffer.Length, fs.Length);
                        else
                            Console.WriteLine("上传失败，失败位置为 ：{0}", fs.Position);
                    }

                });
                t1.IsBackground = true;
                t1.Start();
                t1.Join();//阻塞
            }

        }

        static void UploadTaskTest(FileTransport.Client fileTransport, string fromPath, string toPath)
        {
            int block = 1024 * 1024 * 4;
            byte[] buffer = new byte[block];
            long filesize = new FileInfo(fromPath).Length;
            int readBytes = 0;
            int count = 0;
            long i = 0;

            new WorkOfTask(200, (id) =>
            {
                while (i <= filesize)
                {
                    using (FileStream fs = new FileStream(fromPath, FileMode.Open, FileAccess.Read))
                    {

                        count++;
                        fs.Position = i;
                        readBytes = fs.Read(buffer, 0, buffer.Length);
                        fileTransport.Upload(new DataSegment
                          {
                              CurrentBytes = readBytes,
                              CurrentSeek = fs.Position,
                              Data = buffer,
                              Filename = toPath + Path.GetFileName(fromPath),
                              FileSize = filesize,
                              OrderNumber = count,
                          });
                        Console.WriteLine("当前发送了请求:{3}个,线程为{2},已经上传了{0},共{1}", buffer.Length, fs.Length, id, count);
                    }
                    i += block;

                    if (i >= filesize)
                        return true;
                    else
                        return false;
                }
                return false;
            }, () =>
            {
                fileTransport.UpdateDataSync(new DataSync
                {
                    FilePath = toPath + Path.GetFileName(fromPath),
                    IsSync = false,
                    CurrentSeek = 0,
                    ClientKey = ClientKey,
                    OccurTime = DateTime.Now.ToString(),
                });
            }).Action();


        }
        /// <summary>
        /// 非分块下载
        /// </summary>
        /// <param name="fileTransport"></param>
        /// <param name="fromPath"></param>
        /// <param name="toPath"></param>
        static void DownLoadTest(FileTransport.Client fileTransport, string fromPath, string toPath)
        {
            int block = 1024 * 1024 * 4;
            var sync = fileTransport.IsSync(fromPath, ClientKey);
            if (sync.IsSync)
            {
                #region 下载业务
                using (FileStream stream = new FileStream(toPath + Path.GetFileName(fromPath), FileMode.Append, FileAccess.Write))
                {

                    for (long i = 0; i <= fileTransport.GetFileSize(new DataSync { FilePath = fromPath }); i += block)
                    {
                        var data = fileTransport.Download(new DataSegment { CurrentSeek = i, ClientKey = ClientKey, Filename = fromPath });
                        if (data != null)
                        {
                            stream.Write(data.Data, 0, data.CurrentBytes);
                            Console.WriteLine("已经下载了{0}", data.CurrentBytes);
                        }

                    }

                    //下载完成
                    fileTransport.UpdateDataSync(new DataSync
                    {
                        FilePath = fromPath,
                        IsSync = false,
                        CurrentSeek = 0,
                        ClientKey = ClientKey,
                    });
                    Console.WriteLine("文件下载成功！");

                }

            }
                #endregion
            else
            {
                Console.WriteLine("文件已经下载！");
            }
        }

        /// <summary>
        /// 产生客户端唯一标识
        /// </summary>
        static string ClientKey
        {
            get
            {
                return GetMACAddress();
            }
        }

        //获取本机MAC地址
        static string GetMACAddress()
        {
            string MoAddress = "";
            ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection moc = mc.GetInstances();
            foreach (ManagementObject mo in moc)
            {
                if ((bool)mo["IPEnabled"] == true)
                    MoAddress = mo["MacAddress"].ToString();
                mo.Dispose();
            }
            return MoAddress;
        }

    }
}
